```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JWT 技术详解 - 现代Web认证机制</title>
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
    <link href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    <link href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/mermaid@latest/dist/mermaid.min.js"></script>
    <style>
        :root {
            --primary: #4f46e5;
            --primary-light: #6366f1;
            --primary-dark: #4338ca;
            --secondary: #10b981;
            --dark: #1e293b;
            --light: #f8fafc;
        }
        
        body {
            font-family: 'Noto Sans SC', 'Noto Serif SC', sans-serif;
            color: var(--dark);
            line-height: 1.6;
            background-color: #f9fafb;
        }
        
        .hero {
            background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
        }
        
        .card {
            transition: all 0.3s ease;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
            border-radius: 0.5rem;
        }
        
        .card:hover {
            transform: translateY(-5px);
            box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
        }
        
        .code-block {
            background: #1e1e1e;
            color: #d4d4d4;
            border-radius: 0.375rem;
            font-family: 'Consolas', 'Monaco', 'Andale Mono', monospace;
        }
        
        .section-title {
            position: relative;
            padding-bottom: 0.5rem;
        }
        
        .section-title:after {
            content: '';
            position: absolute;
            bottom: 0;
            left: 0;
            width: 50px;
            height: 3px;
            background: var(--primary);
        }
        
        .first-letter {
            font-size: 3.5rem;
            line-height: 1;
            float: left;
            margin-right: 0.5rem;
            margin-top: 0.25rem;
            color: var(--primary);
            font-weight: 700;
        }
    </style>
</head>
<body class="antialiased">
    <!-- Hero Section -->
    <div class="hero text-white py-20 px-4 md:px-0">
        <div class="container mx-auto max-w-6xl">
            <div class="flex flex-col md:flex-row items-center">
                <div class="md:w-1/2 mb-10 md:mb-0">
                    <h1 class="text-4xl md:text-5xl font-bold mb-4">JSON Web Token (JWT)</h1>
                    <p class="text-xl opacity-90 mb-8">现代Web应用安全认证的最佳实践</p>
                    <div class="flex items-center">
                        <span class="bg-white text-indigo-600 px-4 py-2 rounded-full text-sm font-semibold mr-4">
                            <i class="fas fa-shield-alt mr-2"></i>安全认证
                        </span>
                        <span class="bg-white text-indigo-600 px-4 py-2 rounded-full text-sm font-semibold">
                            <i class="fas fa-code mr-2"></i>开放标准
                        </span>
                    </div>
                </div>
                <div class="md:w-1/2">
                    <div class="bg-white bg-opacity-20 p-8 rounded-lg backdrop-filter backdrop-blur-sm">
                        <div class="mermaid">
                            graph LR
                            A[用户登录] --> B[生成JWT]
                            B --> C[客户端存储]
                            C --> D[携带JWT请求]
                            D --> E[服务端验证]
                            E --> F{验证通过?}
                            F -->|是| G[返回数据]
                            F -->|否| H[拒绝请求]
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- Main Content -->
    <div class="container mx-auto max-w-6xl px-4 py-12">
        <!-- What is JWT Section -->
        <section class="mb-16">
            <h2 class="text-3xl font-bold mb-8 section-title">什么是JWT</h2>
            <div class="grid grid-cols-1 md:grid-cols-2 gap-8">
                <div>
                    <p class="mb-6 text-lg">
                        <span class="first-letter">J</span>SON Web Token（JWT）是一个开放标准（RFC 7519），它定义了一种紧凑且独立的方式，可以在各方之间作为JSON对象安全地传输信息。此信息可以通过数字签名进行验证和信任。JWT可以使用秘密（使用HMAC算法）或使用RSA或ECDSA的公钥/私钥对进行签名。
                    </p>
                    <div class="bg-blue-50 border-l-4 border-blue-500 p-4 mb-6">
                        <p class="text-blue-700">
                            <i class="fas fa-info-circle mr-2"></i>通俗来讲，JWT是一个含签名并携带用户相关信息的加密串，页面请求校验登录接口时，客户端请求头中携带JWT串到后端服务，后端通过签名加密串匹配校验，保证信息未被篡改。
                        </p>
                    </div>
                    <a href="https://jwt.io/introduction/" target="_blank" class="inline-flex items-center text-indigo-600 hover:text-indigo-800 font-medium">
                        访问JWT官网 <i class="fas fa-external-link-alt ml-2"></i>
                    </a>
                </div>
                <div>
                    <div class="card bg-white p-6 h-full">
                        <img src="https://cdn.nlark.com/yuque/0/2024/png/21449790/1708571950906-3ef1ff43-0f7e-4ed2-be0c-6f954382f644.png" alt="JWT示意图" class="rounded-lg w-full h-auto">
                    </div>
                </div>
            </div>
        </section>

        <!-- Problems JWT Solves -->
        <section class="mb-16">
            <h2 class="text-3xl font-bold mb-8 section-title">JWT解决了什么问题</h2>
            <div class="grid grid-cols-1 md:grid-cols-2 gap-8">
                <div class="card bg-white p-6">
                    <img src="https://cdn.nlark.com/yuque/0/2024/png/21449790/1708572181779-e18783b1-dc73-45bb-a204-3edef6b1e181.png" alt="JWT解决的问题" class="rounded-lg w-full h-auto mb-6">
                    
                    <div class="space-y-4">
                        <div class="flex items-start">
                            <div class="bg-indigo-100 p-2 rounded-full mr-4">
                                <i class="fas fa-server text-indigo-600"></i>
                            </div>
                            <div>
                                <h4 class="font-bold text-lg">无状态性（Stateless）</h4>
                                <p>传统的 Session-based 认证需要服务器保存用户状态，而 JWT 是无状态的，它在用户登录后生成 Token 发送给客户端，服务器通过解析 Token 验证用户身份，无需保存 Session 信息。</p>
                            </div>
                        </div>
                        
                        <div class="flex items-start">
                            <div class="bg-green-100 p-2 rounded-full mr-4">
                                <i class="fas fa-globe text-green-600"></i>
                            </div>
                            <div>
                                <h4 class="font-bold text-lg">跨域问题（Cross-Origin）</h4>
                                <p>JWT 可以通过 HTTP 请求头、URL 参数或 Cookie 在不同域名之间传递，适用于跨域认证，方便在不同域名的系统中进行用户认证和授权。</p>
                            </div>
                        </div>
                    </div>
                </div>
                
                <div class="card bg-white p-6">
                    <div class="space-y-4">
                        <div class="flex items-start">
                            <div class="bg-purple-100 p-2 rounded-full mr-4">
                                <i class="fas fa-network-wired text-purple-600"></i>
                            </div>
                            <div>
                                <h4 class="font-bold text-lg">分布式系统支持</h4>
                                <p>在分布式系统中，每个服务都可以使用相同的 JWT 认证方式，无需共享用户 Session 信息，降低了系统的耦合性和复杂度。</p>
                            </div>
                        </div>
                        
                        <div class="flex items-start">
                            <div class="bg-red-100 p-2 rounded-full mr-4">
                                <i class="fas fa-lock text-red-600"></i>
                            </div>
                            <div>
                                <h4 class="font-bold text-lg">安全性</h4>
                                <p>JWT 通过使用数字签名或者加密来保护信息的完整性和机密性，确保传输的数据不被篡改或者窃取。服务器可以验证 JWT 的合法性，并从中解析出用户信息和权限。</p>
                            </div>
                        </div>
                        
                        <div class="mermaid mt-6">
                            pie title JWT优势
                                "无状态性" : 30
                                "跨域支持" : 20
                                "分布式" : 25
                                "安全性" : 25
                        </div>
                    </div>
                </div>
            </div>
        </section>

        <!-- Comparison Section -->
        <section class="mb-16">
            <h2 class="text-3xl font-bold mb-8 section-title">认证方式对比</h2>
            <div class="grid grid-cols-1 md:grid-cols-2 gap-8">
                <div class="card bg-white p-6">
                    <h3 class="text-xl font-bold mb-4 text-indigo-600">传统的Session认证</h3>
                    <img src="https://cdn.nlark.com/yuque/0/2024/png/21449790/1708573404711-888ae657-d1ee-4a6c-977d-3c7473c11aff.png" alt="Session认证流程" class="rounded-lg w-full h-auto mb-6">
                    <p class="mb-4">HTTP协议本身是无状态的，传统Session认证需要在服务器存储用户登录信息，通过Cookie传递Session ID来识别用户。这种方式存在服务器存储压力大、不适合分布式系统等问题。</p>
                    <div class="bg-gray-100 p-4 rounded-lg">
                        <p class="text-sm text-gray-700"><i class="fas fa-exclamation-triangle text-yellow-500 mr-2"></i>问题：服务器需要保存所有用户的Session信息，当用户量增大时，会占用大量服务器内存。</p>
                    </div>
                </div>
                
                <div class="card bg-white p-6">
                    <h3 class="text-xl font-bold mb-4 text-green-600">JWT认证</h3>
                    <img src="https://cdn.nlark.com/yuque/0/2022/png/21449790/1651303282328-3b986ce1-5e37-4250-8973-03f182cb372f.png" alt="JWT认证流程" class="rounded-lg w-full h-auto mb-6">
                    <div class="space-y-4">
                        <div class="flex items-start">
                            <div class="bg-green-100 p-2 rounded-full mr-4">
                                <span class="text-green-600 font-bold">1</span>
                            </div>
                            <div>
                                <p>用户认证后服务器生成JWT并返回给客户端</p>
                            </div>
                        </div>
                        <div class="flex items-start">
                            <div class="bg-green-100 p-2 rounded-full mr-4">
                                <span class="text-green-600 font-bold">2</span>
                            </div>
                            <div>
                                <p>客户端存储JWT并在后续请求中携带</p>
                            </div>
                        </div>
                        <div class="flex items-start">
                            <div class="bg-green-100 p-2 rounded-full mr-4">
                                <span class="text-green-600 font-bold">3</span>
                            </div>
                            <div>
                                <p>服务器验证JWT的有效性并处理请求</p>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </section>

        <!-- JWT Structure Section -->
        <section class="mb-16">
            <h2 class="text-3xl font-bold mb-8 section-title">JWT结构分析</h2>
            <div class="card bg-white p-6 mb-8">
                <img src="https://cdn.nlark.com/yuque/0/2024/png/21449790/1708572763645-f0911529-a253-4146-8c4b-bc5bb01bbc43.png" alt="JWT结构" class="rounded-lg w-full h-auto mb-6">
                
                <div class="grid grid-cols-1 md:grid-cols-3 gap-6">
                    <div class="border-l-4 border-indigo-500 pl-4">
                        <h3 class="font-bold text-lg mb-2">Header (头部)</h3>
                        <p class="mb-4">包含令牌类型和签名算法</p>
                        <div class="code-block p-4 mb-4">
                            <pre class="text-sm"><code class="language-json">{
  "alg": "HS256",
  "typ": "JWT"
}</code></pre>
                        </div>
                    </div>
                    
                    <div class="border-l-4 border-blue-500 pl-4">
                        <h3 class="font-bold text-lg mb-2">Payload (负载)</h3>
                        <p class="mb-4">包含关于实体(通常是用户)和其他数据的声明</p>
                        <div class="code-block p-4 mb-4">
                            <pre class="text-sm"><code class="language-json">{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}</code></pre>
                        </div>
                    </div>
                    
                    <div class="border-l-4 border-purple-500 pl-4">
                        <h3 class="font-bold text-lg mb-2">Signature (签名)</h3>
                        <p class="mb-4">由编码后的头部、负载和密钥组成，用于验证消息完整性</p>
                        <div class="code-block p-4">
                            <pre class="text-sm"><code class="language-javascript">HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret
)</code></pre>
                        </div>
                    </div>
                </div>
                
                <div class="mt-6 p-4 bg-gray-50 rounded-lg">
                    <p class="text-sm">完整的JWT看起来像这样:</p>
                    <div class="bg-gray-800 text-gray-100 p-3 rounded text-sm overflow-x-auto mt-2">
                        eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
                    </div>
                </div>
            </div>
            
            <div class="card bg-white p-6">
                <img src="https://cdn.nlark.com/yuque/0/2022/png/21449790/1651303300831-b8f8d63f-6ef1-4c80-bf1f-33dcdf1bd204.png" alt="JWT传输方式" class="rounded-lg w-full h-auto">
                <p class="mt-4">在客户端发送请求时，JWT 通常放在请求的头部中，形式为 <code class="bg-gray-100 px-2 py-1 rounded">Authorization: Bearer &lt;token&gt;</code>。</p>
            </div>
        </section>

        <!-- Code Examples Section -->
        <section class="mb-16">
            <h2 class="text-3xl font-bold mb-8 section-title">实战示例</h2>
            
            <div class="grid grid-cols-1 md:grid-cols-2 gap-8">
                <div class="card bg-white p-6">
                    <h3 class="text-xl font-bold mb-4 flex items-center">
                        <i class="fas fa-code text-indigo-600 mr-2"></i>生成Token
                    </h3>
                    <div class="code-block p-4 mb-4">
                        <pre class="text-sm"><code class="language-java">@Test
void testCreateToken() {
    // 1.设置超时时间
    Calendar calendar = Calendar.getInstance();
    calendar.add(Calendar.SECOND,30); // 超时时间是30s

    // 2.创建JWTbuilder
    JWTCreator.Builder builder = JWT.create();

    // 3.设置头，负载，签名
    String token = builder
        .withClaim("name", "admin")
        .withClaim("id", 10) // 设置用户自定义属性
        .withExpiresAt(calendar.getTime()) // 设置令牌超时时间
        .sign(Algorithm.HMAC256("dalaoshi"));// 设置用户签名

    // 4.输出结果
    System.out.println(token);
}</code></pre>
                    </div>
                </div>
                
                <div class="card bg-white p-6">
                    <h3 class="text-xl font-bold mb-4 flex items-center">
                        <i class="fas fa-check-circle text-green-600 mr-2"></i>认证Token
                    </h3>
                    <div class="code-block p-4 mb-4">
                        <pre class="text-sm"><code class="language-java">String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...";

// 1.根据用户签签名获取JTW校验器
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("dalaoshi")).build();

// 2.验证token
DecodedJWT verify = jwtVerifier.verify(token);

// 3.获取token的数据
System.out.println(verify.getClaim("name").asString());
System.out.println(verify.getClaim("id").asInt());
System.out.println(verify.getExpiresAt());</code></pre>
                    </div>
                    <div class="bg-yellow-50 border-l-4 border-yellow-400 p-4">
                        <h4 class="font-bold mb-2">常见异常</h4>
                        <ul class="list-disc pl-5 space-y-1 text-sm">
                            <li><span class="font-medium">SignatureVerificationException:</span> 签名不一致异常</li>
                            <li><span class="font-medium">TokenExpiredException:</span> 令牌过期异常</li>
                            <li><span class="font-medium">AlgorithmMismatchException:</span> 算法不匹配异常</li>
                            <li><span class="font-medium">InvalidClaimException:</span> 失效的payload异常</li>
                        </ul>
                    </div>
                </div>
            </div>
        </section>

        <!-- Implementation Section -->
        <section class="mb-16">
            <h2 class="text-3xl font-bold mb-8 section-title">实现细节</h2>
            
            <div class="grid grid-cols-1 md:grid-cols-2 gap-8">
                <div class="card bg-white p-6">
                    <h3 class="text-xl font-bold mb-4 flex items-center">
                        <i class="fas fa-key text-purple-600 mr-2"></i>签名过程
                    </h3>
                    <div class="code-block p-4 mb-4">
                        <pre class="text-sm"><code class="language-java">private String sign() throws SignatureGenerationException {
    // 把头进行base64编码成字符串
    String header = Base64.encodeBase64URLSafeString(
        headerJson.getBytes(StandardCharsets.UTF_8));
    
    // 把payLoad进行base64编码成字符串
    String payload = Base64.encodeBase64URLSafeString(
        payloadJson.getBytes(StandardCharsets.UTF_8));
    
    // 把两个字符串用.连接
    String content = String.format("%s.%s", header, payload);

    // 用签名算法签名上面拼接好的字符串
    byte[] signatureBytes = algorithm.sign(
        content.getBytes(StandardCharsets.UTF_8));
    
    // 把字节数组用Base64编码成一个字符串
    String signature = Base64.encodeBase64URLSafeString(
        (signatureBytes));

    // 把的字符串拼接到上面的字符串的后面
    return String.format("%s.%s", content, signature);
}</code></pre>
                    </div>
                    <img src="https://cdn.nlark.com/yuque/0/2022/png/21449790/1653318792205-afa703e4-d3c7-4817-b14e-4f658ba84929.png" alt="签名过程" class="rounded-lg w-full h-auto">
                </div>
                
                <div class="card bg-white p-6">
                    <h3 class="text-xl font-bold mb-4 flex items-center">
                        <i class="fas fa-search text-blue-600 mr-2"></i>验证过程
                    </h3>
                    <div class="code-block p-4 mb-4">
                        <pre class="text-sm"><code class="language-java">public DecodedJWT verify(String token) throws JWTVerificationException {
    // 解析token中的头和载荷到DecodeJWT对象
    DecodedJWT jwt = JWT.decode(token);
    
    // 检查签名算法是否匹配
    verifyAlgorithm(jwt, algorithm);
    
    // 验证签名是否一致
    algorithm.verify(jwt);
    
    // 验证载荷，过期时间
    verifyClaims(jwt, claims);
    return jwt;
}</code></pre>
                    </div>
                    <div class="bg-blue-50 p-4 rounded-lg">
                        <p class="text-sm text-blue-800"><i class="fas fa-lightbulb text-blue-600 mr-2"></i>实现JWT自校验的关键是把token字符串中解析出头和负载，使用校验的签名内容进行二次签名，然后与token中的签名内容对比，如果一致则验证成功。</p>
                    </div>
                    <img src="https://cdn.nlark.com/yuque/0/2022/png/21449790/1653318836779-36c57e39-1663-4780-b351-cb63ea37bd24.png" alt="验证过程" class="rounded-lg w-full h-auto mt-4">
                </div>
            </div>
        </section>

        <!-- Utils Section -->
        <section class="mb-16">
            <h2 class="text-3xl font-bold mb-8 section-title">工具类封装</h2>
            
            <div class="card bg-white p-6">
                <div class="code-block p-4">
                    <pre class="text-sm"><code class="language-java">public class JWTUtils {
    private static String sign = "dalaoshi";

    public static String createToken(Map&lt;String, String&gt; map) {
        // 1.设置超时时间
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 7); // 7天

        // 2.创建JWTbuilder
        JWTCreator.Builder builder = JWT.create();

        // 设置负载数据
        Set&lt;Map.Entry&lt;String, String&gt;&gt; entries = map.entrySet();
        for (Map.Entry&lt;String, String&gt; entrie : entries) {
            builder.withClaim(entrie.getKey(), entrie.getValue());
        }
        // 3.设置签名，过期时间
        String token = builder
                .withExpiresAt(calendar.getTime()) // 设置令牌超时时间
                .sign(getSignature());// 设置用户签名

        // 4.返回
        return token;
    }

    // 获取签名算法
    public static Algorithm getSignature() {
        return Algorithm.HMAC256(sign);
    }

    // 校验
    public static DecodedJWT require(String token) {
        return JWT.require(getSignature()).build().verify(token);
    }

    // 获取token中的数据
    public static Claim getPayload(String token, String key) {
        return require(token).getClaim(key);
    }
}</code></pre>
                </div>
            </div>
        </section>

        <!-- Web Integration -->
        <section class="mb-16">
            <h2 class="text-3xl font-bold mb-8 section-title">Web集成</h2>
            
            <div class="grid grid-cols-1 md:grid-cols-2 gap-8">
                <div class="card bg-white p-6">
                    <h3 class="text-xl font-bold mb-4 flex items-center">
                        <i class="fas fa-sign-in-alt text-indigo-600 mr-2"></i>登录接口
                    </h3>
                    <div class="code-block p-4 mb-4">
                        <pre class="text-sm"><code class="language-java">@RequestMapping("/login")
public ResultEntity login(String username,String password){
    ResultEntity resultEntity = userService.login(username, password);
    if(ResultEntity.SUCEESS.equals(resultEntity.getStatus())){
        Map&lt;String,String&gt; map = new HashMap&lt;&gt;();
        map.put("id","10");
        map.put("username",username);

        String token = JWTUtils.createToken(map);
        return ResultEntity.success(token);
    }else{
        return ResultEntity.error("登录失败");
    }
}</code></pre>
                    </div>
                    
                    <h3 class="text-xl font-bold mb-4 flex items-center mt-6">
                        <i class="fas fa-check-shield text-green-600 mr-2"></i>Token验证
                    </h3>
                    <div class="code-block p-4">
                        <pre class="text-sm"><code class="language-java">@RequestMapping("/require")
public ResultEntity require(String token){
    try {
        DecodedJWT require = JWTUtils.require(token);
        return ResultEntity.response(require);
    }catch (TokenExpiredException e){
        return ResultEntity.error("token过期");
    }catch (SignatureVerificationException e){
        return ResultEntity.error("用户签名不一致");
    } catch (InvalidClaimException e){
        return ResultEntity.error("payload数据有误");
    }catch (Exception e){
        return ResultEntity.error("校验失败");
    }
}</code></pre>
                    </div>
                </div>
                
                <div class="card bg-white p-6">
                    <h3 class="text-xl font-bold mb-4 flex items-center">
                        <i class="fas fa-filter text-blue-600 mr-2"></i>拦截器实现
                    </h3>
                    <div class="code-block p-4 mb-4">
                        <pre class="text-sm"><code class="language-java">@Override
public boolean preHandle(HttpServletRequest request, 
        HttpServletResponse response, Object handler) {
    // 1.获取token
    String token = request.getHeader("token");
    Map&lt;String,Object&gt; map = new HashMap&lt;&gt;();
    try {
        // 2.校验
        JWTUtils.verify(token);
        return true;
    }catch (TokenExpiredException e){
        return ResultEntity.error("token过期");
    }catch (SignatureVerificationException e){
        return ResultEntity.error("用户签名不一致");
    } catch (InvalidClaimException e){
        return ResultEntity.error("payload数据有误");
    }catch (Exception e){
        return ResultEntity.error("校验失败");
    }
    
    // 3.校验失败响应数据
    String json = new ObjectMapper().writeValueAsString(map);
    response.setContentType("application/json;charset=UTF-8");
    response.getWriter().println(json);
    return false;
}</code></pre>
                    </div>
                    
                    <h3 class="text-xl font-bold mb-4 flex items-center mt-6">
                        <i class="fas fa-route text-purple-600 mr-2"></i>网关路由校验
                    </h3>
                    <div class="code-block p-4">
                        <pre class="text-sm"><code class="language-java">@Override
public Object run() throws ZuulException {
    RequestContext ctx = RequestContext.getCurrentContext();
    HttpServletRequest request = ctx.getRequest();
    
    // 1.该服务是否需要验证
    if(needAuth(request.getRequestURL().toString())){
        String token = request.getHeader("token");
        // 2.验证服务
        ResultEntity result = ssoService.require(token);
        if(!ResultEntity.SUCEESS.equals(result.getStatus())){
            ctx.setSendZuulResponse(false); // 不能往下执行
            ctx.getResponse().setContentType("application/json;charset=utf-8");
            ctx.setResponseBody(JSON.toJSONString(
                ResultEntity.error("校验未通过")));
        }
    }
    return null;
}</code></pre>
                    </div>
                </div>
            </div>
        </section>

        <!-- Advanced Topics -->
        <section>
            <h2 class="text-3xl font-bold mb-8 section-title">高级话题</h2>
            
            <div class="grid grid-cols-1 md:grid-cols-2 gap-8">
                <div class="card bg-white p-6">
                    <h3 class="text-xl font-bold mb-4 flex items-center">
                        <i class="fas fa-users text-red-600 mr-2"></i>多用户登录问题
                    </h3>
                    <img src="https://cdn.nlark.com/yuque/0/2022/png/21449790/1653319055821-160fa9a2-e39c-4c45-8cb0-b50d1ff768cd.png" alt="多用户登录" class="rounded-lg w-full h-auto mb-4">
                    <p class="mb-4">如果一个用户登录在多个设备登录，就会出现一个用户多个token在多个设备上同时登录。要解决这个问题就要判断用户操作的token是否是最新的。</p>
                    <div class="code-block p-4">
                        <pre class="text-sm"><code class="language-java">// login
public String login(String name,String password){
    // 1.查询数据库认证
    // 2.生成token
    String token = "";
    // 3.把用户最新的token放入到redis中
    redisTemp.set(username,token); // username作为key
}

// 路由校验
// 1.获取用户token
// 2.根据用户名查询用户最新的token
// 3.对比两个token是否一致
//   不一致说明用户进行了第二次登陆，不让认证通过</code></pre>
                    </div>
                </div>
                
                <div class="card bg-white p-6">
                    <h3 class="text-xl font-bold mb-4 flex items-center">
                        <i class="fas fa-laptop-code text-green-600 mr-2"></i>客户端处理
                    </h3>
                    <img src="https://cdn.nlark.com/yuque/0/2022/png/21449790/1653319092891-af721ba0-53a1-4b61-bd46-2760fab2ca66.png" alt="客户端处理" class="rounded-lg w-full h-auto mb-4">
                    
                    <h4 class="font-bold mb-2 mt-4">保存Token</h4>
                    <div class="code-block p-4 mb-4">
                        <pre class="text-sm"><code class="language-javascript">function login(){
    $.post("http://localhost/sso/login",param,function(data){
        if(data.status = "success"){
            // 获取token并保存到本地存储
            localStorage.setItem("login-token",data.data);
        }
    },"JSON");
}</code></pre>
                    </div>
                    
                    <h4 class="font-bold mb-2">携带Token</h4>
                    <div class="code-block p-4">
                        <pre class="text-sm"><code class="language-javascript">function sendRequest(){
    $.ajax({
        url: "http://localhost/addXxxxx",
        beforeSend: function (xhr) {
            // 从本地存储获取token添加到请求头
            xhr.setRequestHeader("Authorization", 
                localStorage.getItem("login-token"));
        },
        success: function (result) {
            // 处理结果
        }
    });
}</code></pre>
                    </div>
                    
                    <div class="bg-gray-100 p-4 rounded-lg mt-4">
                        <h4 class="font-bold mb-2">为什么使用Authorization头？</h4>
                        <ul class="list-disc pl-5 space-y-1 text-sm">
                            <li>与普通参数区分</li>
                            <li>解决跨域问题(Cookie有跨域限制)</li>
                            <li>Authorization header就是为认证设计的</li>
                            <li>解决XSS和XSRF问题</li>
                        </ul>
                    </div>
                </div>
            </div>
        </section>
    </div>

    <script>
        mermaid.initialize({
            startOnLoad: true,
            theme: 'default',
            flowchart: {
                useMaxWidth: true,
                htmlLabels: true,
                curve: 'basis'
            }
        });
    </script>
</body>
</html>
```